<!-- 角色管理 -->
<template>
  <div class="roleManage sys-content">
    <page-mod>
      <el-card>
        <div class="query-box">
          <el-form :model="query" inline>
            <el-form-item label="角色名称:">
              <el-input v-model="query.name" placeholder="请输入角色名称" clearable/>
            </el-form-item>
          </el-form>
          <div class="btns">
            <el-button icon="Search" color="#16b777" @click="load(1)">查询</el-button>
            <el-button icon="Plus" color="#FFB800" @click="show = true">新增</el-button>
            <el-button icon="Refresh" color="#FF5722" @click="resetSearch">重置</el-button>
          </div>
        </div>
      </el-card>
    </page-mod>
    <page-mod title="角色数据" icon="Histogram" :showBtn="false" :padBottom="false">
      <el-card v-loading="loading" element-loading-text="拼命加载中">
        <el-table ref="tableRef" :data="dataList" max-height="493" border>
          <el-table-column label="序号" type="index" align="center" width="60"/>
          <el-table-column label="角色名称" prop="name" align="center"></el-table-column>
          <el-table-column label="角色代码" prop="roleCode" align="center"></el-table-column>
          <el-table-column label="描述" prop="description" header-align="center"></el-table-column>
          <el-table-column label="创建时间" prop="createdTime" align="center">
            <template #default="{row}">
              <span>{{ $date(row.createdTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
            </template>
          </el-table-column>
          <el-table-column label="操作" align="center" width="250">
            <template #default="{row}">
              <el-button type="success" icon="View" link @click="toAccess(row.roleId)">授权</el-button>
              <el-divider direction="vertical" />
              <el-button type="primary" icon="Edit" link @click="toUpdate(row)">修改</el-button>
              <el-divider direction="vertical" />
              <el-button type="danger" icon="Delete" link @click="doDelete(row.roleId)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <el-pagination 
          class="paging"
          v-show="query.total"
          small
          layout="total, sizes, prev, pager, next, jumper" 
          :current-page="query.current" 
          :page-size="query.size"
          :total="query.total"
          @current-change="load"
          @size-change="sizeChange">
        </el-pagination>
      </el-card>
    </page-mod>

    <!-- 新增、编辑弹窗 -->
    <el-dialog v-model="show" :title="form.roleId ? '编辑' : '新增'" top="10vh" width="23%" center draggable @close="resetForm">
      <el-form ref="formRef" :model="form" :rules="rules" size="default" label-width="95px">
        <el-form-item label="角色名称:" prop="name" required>
          <el-input v-model="form.name" placeholder="请输入角色名称" clearable/>
        </el-form-item>
        <el-form-item label="角色代码:" prop="roleCode" required>
          <el-input v-model="form.roleCode" placeholder="例如：ROLE_abc" clearable/>
        </el-form-item>
        <el-form-item label="描述:" prop="description">
          <el-input v-model="form.description" type="textarea" rows="5" placeholder="请输入描述" clearable/>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button type="primary" size="default" @click="doSubmit">保存</el-button>
        <el-button size="default" @click="show = false">关闭</el-button>
      </template>
    </el-dialog>

    <!-- 角色授权弹窗 -->
    <el-dialog v-model="accessShow" title="授予权限" top="10vh" width="23%" center draggable class="access-dialog">
      <el-tree
        ref="treeRef"
        node-key="defaultMenuId"
        show-checkbox
        default-expand-all
        :data="menus"
        :props="{label: 'name', children: 'childList'}">
      </el-tree>
      <template #footer>
        <el-button type="primary" size="default" @click="doAccess">保存</el-button>
        <el-button size="default" @click="accessShow = false">关闭</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup name="roleManage">
  import { cudRoleApi, getRolePagesApi, getMenusApi, setRoleAccessApi, getRoleAccessApi } from '@/api/api'
  import { ref, reactive, toRefs, getCurrentInstance, onActivated, nextTick } from 'vue'

  // 获取注册的全局实列
  const currentThis = getCurrentInstance().appContext.config.globalProperties

  const formRef = ref(null)
  const treeRef = ref(null)

  const currentData = reactive({
    loading: false,
    show: false,
    accessShow: false,
    query: {
      name: '',
      current: 1,
      size: 20,
      total: 0
    },
    menus: [
      {id: '1', pid: '0', name: '首页', pname: '', icon: 'icon zcytIcon zcyt-kanban', type: '1', path: 'home', order: 1, status: 0, children: []},
      {id: '2', pid: '0', name: '权限设置', pname: '', icon: 'icon zcytIcon zcyt-quanxian2', type: '1', path: '', order: 2, status: 1, children: [
        {id: '21', pid: '2', name: '菜单管理', pname: '权限设置', icon: '', type: '2', path: 'menuManage', order: 21, status: 1, children: []},
        {id: '22', pid: '2', name: '角色管理', pname: '权限设置', icon: '', type: '2', path: 'roleManage', order: 22, status: 1, children: []},
        {id: '23', pid: '2', name: '用户管理', pname: '权限设置', icon: '', type: '2', path: 'userManage', order: 23, status: 1, children: []}
      ]}
    ],
    dataList: [],
    form: {
      roleId: '',
      name: '',
      roleCode: '',
      description: ''
    },
    rules: {
      name: [{ required: true, message: '请输入角色名称', trigger: ['blur', 'change'] }],
      roleCode: [
        { 
          required: true, trigger: ['blur', 'change'], validator: (rule, value, callback) => {
            if(!value) {
              callback(new Error('请输入角色代码'))
            } else {
              if(!/^ROLE_[a-zA-Z0-9|_]+$/.test(value)) {
                callback(new Error('前缀必须是ROLE_,链接使用_,必须是字母数字'))
              } else {
                callback()
              }
            }
          } 
        }
      ]
    },
    accessForm: {
      roleId: '',
      defaultMenuIdList: []
    }
  })
  let {loading, show, accessShow, query, menus, dataList, form, rules, accessForm} = toRefs(currentData)

  // 查询
  function load(page) {
    currentData.loading = true
    currentData.query.current = page
    getRolePagesApi(currentData.query).then(res => {
      currentData.loading = false
      if(res.code === '200') {
        currentData.dataList = res.data.pages
        currentData.query.total = res.data.total
      } else {
        currentThis.$message.error(res.message)
      }
    })
  }
  
  // 重置查询
  function resetSearch() {
    currentData.query.name = ''
    load(1)
  }

  // 新增或编辑
  function doSubmit() {
    formRef.value.validate((valid) => {
      if (valid) {
        currentThis.$messageBox.confirm(`确认${currentData.form.roleId ? '修改' : '新增'}吗？`).then(() => {
          let loading = currentThis.$loading(`正在${currentData.form.roleId ? '修改' : '新增'}`)
          cudRoleApi(`${currentData.form.roleId ? 'update' : 'save'}`, currentData.form).then(res => { // 修改
            loading.close()
            if(res.code === '200') {
              currentThis.$message.success(res.message)
              currentData.show = false
              if(currentData.form.roleId) {
                load(currentData.query.current)
              } else {
                load(1)
              }
            } else {
              currentThis.$message.error(res.message)
            }
          })
        }).catch(() => {})
      } else {
        return false;
      }
    })
  }

  // 修改前弹窗
  function toUpdate(e) {
    currentData.form = {...e}
    currentData.show = true
  }

  // 删除
  function doDelete(roleId) {
    currentThis.$messageBox.confirm('确认删除吗？').then(() => {
      let loading = currentThis.$loading('删除中，请耐心等待')
      cudRoleApi('delete', { id: roleId }).then(res => {
        loading.close()
        if(res.code === '200') {
          currentThis.$message.success(res.message)
          load(currentData.query.current)
        } else {
          currentThis.$message.error(res.message)
        }
      })
    }).catch(() => {})
  }

  // 给角色授权菜单弹窗
  function toAccess(roleId) {
    currentData.accessForm.roleId = roleId
    currentData.accessForm.defaultMenuIdList = []
    currentData.accessShow = true
    nextTick(() => {
      getRoleAccessApi(roleId).then(res => {
        if(res.code === '200') {
          let menus = []
          res.data.forEach(item => {
            if(item.childList !== null && item.childList.length !== 0) {
              item.childList.forEach(e => {
                menus.push(e)
              })
            } else {
              menus.push(item)
            }
          })
          treeRef.value.setCheckedNodes(menus)
        } else {
          currentThis.$message.error('获取角色权限失败')
        }
      })
    })
  }

  // 执行授权
  function doAccess() {
    let trees = treeRef.value.getCheckedNodes(false, true)
    if(!trees.length) {
      currentThis.$message.error('请选择菜单')
      return
    }
    currentThis.$messageBox.confirm('确认授权吗？').then(() => {
      let loading = currentThis.$loading('授权中，请耐心等待')
      let menus = []
      trees.forEach(item => {
        menus.push(item.defaultMenuId)
      })
      currentData.accessForm.defaultMenuIdList = menus
      setRoleAccessApi(currentData.accessForm).then(res => {
        loading.close()
        if(res.code === '200') {
          currentData.accessShow = false
          currentThis.$message.success(res.message)
        } else {
          currentThis.$message.error(res.message)
        }
      })
    }).catch(() => {})
  }

  // 新增编辑弹窗重置数据
  function resetForm() {
    currentData.form = {
      roleId: '',
      name: '',
      roleCode: '',
      description: ''
    }
    formRef.value.resetFields()
  }

  // 分页每页显示条数改变执行
  function sizeChange(size) {
    currentData.query.size = size
    load(1)
  }

  // 初始化平台菜单数据，用于给权限设置菜单权限
  function initMenus() {
    getMenusApi().then(res => {
      if(res.code === '200') {
        currentData.menus = res.data
      } else {
        currentThis.$message.error(res.message)
      }
    })
  }

  onActivated(() => {
    load(currentData.query.current)
    initMenus()
  })
</script>

<style lang="less" scoped>
.roleManage{
  :deep(.el-dialog){
    .el-input, .el-textarea{
      width: 300px;
    }
  }
  :deep(.access-dialog.el-dialog){
    .el-dialog__body{
      max-height: 400px;
      overflow: hidden auto;
    }
  }
}
</style>